--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
meshchatx/src/backend/docs_manager.py 415abdb00a932473a2ffaf53f6b8fcaa6b0605ac (415abdb0) Text, 38.13 KB
T8b949e# SPDX-License-Identifier: 0BSD
Tff7b72import T7ee787html
Tff7b72import T7ee787io
Tff7b72import T7ee787json
Tff7b72import T7ee787logging
Tff7b72import T7ee787os
Tff7b72import T7ee787re
Tff7b72import T7ee787shutil
Tff7b72import T7ee787zipfile
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787markdown_renderer Tff7b72import Te6edf3MarkdownRenderer
Te6edf3BUNDLED_DOCS_SUBDIR Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Ta5d6ff"Ta5d6ffreticulum-docs-bundledTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffcurrentTa5d6ff"Tb4b4b4)
Te6edf3MANIFEST_FILENAME Tff7b72= Ta5d6ff"Ta5d6ffmanifest.jsonTa5d6ff"
Te6edf3DOC_FILE_SUFFIXES Tff7b72= Tb4b4b4(Ta5d6ff"Ta5d6ff.mdTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff.txtTa5d6ff"Tb4b4b4)
Tff7b72class T56d364DocsManagerTb4b4b4:
T8b949e"""Manages the bundled Reticulum manual and any user-uploaded overrides.
The Reticulum manual is shipped with the application under
``<public_dir>/reticulum-docs-bundled/current``. Users may upload a
replacement archive which is extracted into ``<storage_dir>/reticulum-docs``
and takes precedence at request time. Removing the user upload restores the
bundled copy. There is no runtime download path. Fresh manuals are staged at
build time with ``scripts/build/fetch_reticulum_manual.py`` (``pnpm run build-docs``).
"""
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3configTb4b4b4, Te6edf3public_dirTb4b4b4, Te6edf3project_rootTff7b72=Tff7b72NoneTb4b4b4, Te6edf3storage_dirTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffconfig Tff7b72= Te6edf3config
Tff7b72selfTff7b72.Td2a8ffpublic_dir Tff7b72= Te6edf3public_dir
Tff7b72selfTff7b72.Td2a8ffproject_root Tff7b72= Te6edf3project_root
Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72= Te6edf3storage_dir
Tff7b72if Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdocs_base_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4, Ta5d6ff"Ta5d6ffreticulum-docsTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx-docsTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdocs_base_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4, Ta5d6ff"Ta5d6ffreticulum-docsTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx-docsTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdocs_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_base_dirTb4b4b4, Ta5d6ff"Ta5d6ffcurrentTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffversions_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_base_dirTb4b4b4, Ta5d6ff"Ta5d6ffversionsTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffbundled_docs_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4, Te6edf3BUNDLED_DOCS_SUBDIRTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffupload_status Tff7b72= Ta5d6ff"Ta5d6ffidleTa5d6ff"
Tff7b72selfTff7b72.Td2a8ffupload_progress Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72for Te6edf3d Tff7b72in Tb4b4b4[
Tff7b72selfTff7b72.Td2a8ffdocs_base_dirTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4,
Tb4b4b4]Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3dTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3dTb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4) Tff7b72or Tff7b72not Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_update_current_linkTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSError Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to create documentation directories: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Tffa657strTb4b4b4(Te6edf3eTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4) Tff7b72and Te6edf3osTff7b72.Td2a8ffaccessTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4,
Te6edf3osTff7b72.Td2a8ffW_OKTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpopulate_meshchatx_docsTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_update_current_linkTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3versionTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e"""Update the 'current' directory to point at the chosen or latest version."""
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4)Tb4b4b4:
Tff7b72return
Te6edf3versions Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_available_versionsTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3versionsTb4b4b4:
Tff7b72return
Te6edf3target_version Tff7b72= Te6edf3version Tff7b72or Te6edf3versionsTb4b4b4[Tff7b72-T79c0ff1Tb4b4b4]
Te6edf3version_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4, Te6edf3target_versionTb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3version_pathTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffislinkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_remove_tree_force_writableTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3rel_target Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3version_pathTb4b4b4, Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffsymlinkTb4b4b4(Te6edf3rel_targetTb4b4b4, Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149OSErrorTb4b4b4, Tf85149AttributeErrorTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffcopytreeTb4b4b4(Te6edf3version_pathTb4b4b4, Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)
Tff7b72def Td2a8ffget_available_versionsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]
Te6edf3versions Tff7b72= Tb4b4b4[
Te6edf3d
Tff7b72for Te6edf3d Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4, Te6edf3dTb4b4b4)Tb4b4b4)
Tb4b4b4]
Tff7b72return Tffa657sortedTb4b4b4(Te6edf3versionsTb4b4b4)
Tff7b72def Td2a8ffget_current_versionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffislinkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3osTff7b72.Td2a8ffreadlinkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4)
Te6edf3version_file Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4, Ta5d6ff"Ta5d6ff.versionTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3version_fileTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3version_fileTb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72return Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72pass
Tff7b72if Tff7b72selfTff7b72.Td2a8ffhas_user_docsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffunknownTa5d6ff"
Tff7b72if Tff7b72selfTff7b72.Td2a8ffhas_bundled_docsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffbundledTa5d6ff"
Tff7b72return Tff7b72None
Tff7b72def Td2a8ffswitch_versionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3versionTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3version Tff7b72in Tff7b72selfTff7b72.Td2a8ffget_available_versionsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_update_current_linkTb4b4b4(Te6edf3versionTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72return Tff7b72False
Tff7b72def Td2a8ffdelete_versionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3versionTb4b4b4)Tb4b4b4:
T8b949e"""Delete a specific user-uploaded version of the documentation."""
Tff7b72if Te6edf3version Tff7b72not Tff7b72in Tff7b72selfTff7b72.Td2a8ffget_available_versionsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Te6edf3version_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4, Te6edf3versionTb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3version_pathTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Te6edf3current_version Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_current_versionTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3current_version Tff7b72== Te6edf3versionTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffislinkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_remove_tree_force_writableTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_remove_tree_force_writableTb4b4b4(Te6edf3version_pathTb4b4b4)
Tff7b72if Te6edf3current_version Tff7b72== Te6edf3versionTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_update_current_linkTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72True
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to delete docs version Tffd700{Te6edf3versionTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72False
Tff7b72def Td2a8ffclear_reticulum_docsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Remove every user-uploaded Reticulum doc; bundled copy is untouched."""
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_base_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3item Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_base_dirTb4b4b4)Tb4b4b4:
Te6edf3item_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_base_dirTb4b4b4, Te6edf3itemTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffislinkTb4b4b4(Te6edf3item_pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3item_pathTb4b4b4)
Tff7b72elif Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3item_pathTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_remove_tree_force_writableTb4b4b4(Te6edf3item_pathTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3item_pathTb4b4b4)
Tff7b72for Te6edf3d Tff7b72in Tb4b4b4[Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4, Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4]Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3dTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3dTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to clear Reticulum docs: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72False
Tff7b72def Td2a8ffpopulate_meshchatx_docsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Copy the project's bundled MeshChatX markdown docs into storage."""
Te6edf3search_paths Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72if Tff7b72selfTff7b72.Td2a8ffproject_rootTb4b4b4:
Te6edf3search_pathsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffproject_rootTb4b4b4, Ta5d6ff"Ta5d6ffdocsTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3search_pathsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4, Ta5d6ff"Ta5d6ffmeshchatx-docsTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3this_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Tff7b72__file__Tb4b4b4)Tb4b4b4)
Te6edf3search_pathsTff7b72.Td2a8ffappendTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3this_dirTb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdocsTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3candidate_dirs Tff7b72= Tb4b4b4[Te6edf3p Tff7b72for Te6edf3p Tff7b72in Te6edf3search_paths Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3pTb4b4b4)Tb4b4b4]
Tff7b72if Tff7b72not Te6edf3candidate_dirsTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffwarningTb4b4b4(Ta5d6ff"Ta5d6ffMeshChatX docs source directory not found.Ta5d6ff"Tb4b4b4)
Tff7b72return
Te6edf3src_docs Tff7b72= Te6edf3candidate_dirsTb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72for Te6edf3base Tff7b72in Te6edf3candidate_dirsTb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3baseTb4b4b4, Te6edf3MANIFEST_FILENAMETb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3src_docs Tff7b72= Te6edf3base
Tff7b72break
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffaccessTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4, Te6edf3osTff7b72.Td2a8ffW_OKTb4b4b4)Tb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffwarningTb4b4b4(Ta5d6ff"Ta5d6ffMeshChatX docs directory is not writable.Ta5d6ff"Tb4b4b4)
Tff7b72return
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_sync_docs_treeTb4b4b4(Te6edf3src_docsTb4b4b4, Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_render_meshchatx_html_exportsTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to populate MeshChatX docs: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ff_sync_docs_treeTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3src_docsTb4b4b4, Te6edf3dest_dirTb4b4b4)Tb4b4b4:
T8b949e"""Copy manifest, markdown, and text files from src_docs into dest_dir.
Skips ``agents/`` (contributor and automated-agent guidance, not
end-user documentation).
"""
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3dirnamesTb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Te6edf3src_docsTb4b4b4)Tb4b4b4:
Te6edf3rel_root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3src_docsTb4b4b4)
Tff7b72if Te6edf3rel_root Tff7b72== Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4:
Te6edf3dirnamesTb4b4b4[Tb4b4b4:Tb4b4b4] Tff7b72= Tb4b4b4[Te6edf3d Tff7b72for Te6edf3d Tff7b72in Te6edf3dirnames Tff7b72if Te6edf3d Tff7b72!= Ta5d6ff"Ta5d6ffagentsTa5d6ff"Tb4b4b4]
Tff7b72elif Te6edf3rel_root Tff7b72== Ta5d6ff"Ta5d6ffagentsTa5d6ff" Tff7b72or Te6edf3rel_rootTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffagentsTffd700{Te6edf3osTff7b72.Td2a8ffsepTffd700}Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3dirnamesTb4b4b4[Tb4b4b4:Tb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72continue
Te6edf3target_root Tff7b72= Tb4b4b4(
Te6edf3dest_dir Tff7b72if Te6edf3rel_root Tff7b72== Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72else Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3dest_dirTb4b4b4, Te6edf3rel_rootTb4b4b4)
Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3target_rootTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72for Te6edf3file Tff7b72in Te6edf3filesTb4b4b4:
Tff7b72if Te6edf3file Tff7b72== Te6edf3MANIFEST_FILENAME Tff7b72or Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Te6edf3DOC_FILE_SUFFIXESTb4b4b4)Tb4b4b4:
Te6edf3src_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)
Te6edf3dest_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3target_rootTb4b4b4, Te6edf3fileTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3src_pathTb4b4b4) Tff7b72!= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3dest_pathTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffcopy2Tb4b4b4(Te6edf3src_pathTb4b4b4, Te6edf3dest_pathTb4b4b4)
Tff7b72def Td2a8ff_render_meshchatx_html_exportsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3index_linksTb4b4b4: Tffa657listTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3manifestTb4b4b4, Te6edf3_manifest_error Tff7b72= Tff7b72selfTff7b72.Td2a8ff_read_manifestTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3manifest Tff7b72and Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsectionsTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3section Tff7b72in Tffa657sortedTb4b4b4(
Te6edf3manifestTb4b4b4[Ta5d6ff"Ta5d6ffsectionsTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3sTb4b4b4: Te6edf3sTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fforderTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)
Tb4b4b4)Tb4b4b4:
Te6edf3section_title Tff7b72= Tff7b72selfTff7b72.Td2a8ff_localized_textTb4b4b4(
Te6edf3sectionTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdefault_languageTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3section_titleTb4b4b4:
Te6edf3index_linksTff7b72.Td2a8ffappendTb4b4b4(
Ta5d6fffTa5d6ff'Ta5d6ff<li class=Ta5d6ff"Ta5d6ffmb-1 text-sm font-bold text-zinc-300 mt-4Ta5d6ff"Ta5d6ff>Tffd700{Te6edf3htmlTff7b72.Td2a8ffescapeTb4b4b4(Te6edf3section_titleTb4b4b4)Tffd700}Ta5d6ff</li>Ta5d6ff'Tb4b4b4,
Tb4b4b4)
Tff7b72for Te6edf3item Tff7b72in Te6edf3sectionTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffitemsTa5d6ff"Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4:
Te6edf3rel_path Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3rel_path Tff7b72or Tff7b72not Te6edf3rel_pathTff7b72.Td2a8ffendswithTb4b4b4(Te6edf3DOC_FILE_SUFFIXESTb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3title Tff7b72= Tff7b72selfTff7b72.Td2a8ff_localized_textTb4b4b4(
Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflangTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdefault_languageTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3html_file Tff7b72= Tff7b72selfTff7b72.Td2a8ff_doc_html_nameTb4b4b4(Te6edf3rel_pathTb4b4b4)
Tff7b72if Te6edf3titleTb4b4b4:
Te6edf3index_linksTff7b72.Td2a8ffappendTb4b4b4(
Ta5d6fffTa5d6ff'Ta5d6ff<li class=Ta5d6ff"Ta5d6ffmb-2 ml-3Ta5d6ff"Ta5d6ff><a href=Ta5d6ff"Tffd700{Te6edf3htmlTff7b72.Td2a8ffescapeTb4b4b4(Te6edf3html_fileTb4b4b4)Tffd700}Ta5d6ff"Ta5d6ff class=Ta5d6ff"Ta5d6fftext-blue-400 hover:text-blue-300Ta5d6ff"Ta5d6ff>Tffd700{Te6edf3htmlTff7b72.Td2a8ffescapeTb4b4b4(Te6edf3titleTb4b4b4)Tffd700}Ta5d6ff</a></li>Ta5d6ff'Tb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_write_doc_html_exportTb4b4b4(Te6edf3rel_pathTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72for Te6edf3doc Tff7b72in Tff7b72selfTff7b72.Td2a8ff_collect_flat_docsTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3rel_path Tff7b72= Te6edf3docTb4b4b4[Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4]
Te6edf3html_file Tff7b72= Tff7b72selfTff7b72.Td2a8ff_write_doc_html_exportTb4b4b4(Te6edf3rel_pathTb4b4b4)
Tff7b72if Te6edf3html_fileTb4b4b4:
Te6edf3label Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3rel_pathTb4b4b4)
Te6edf3index_linksTff7b72.Td2a8ffappendTb4b4b4(
Ta5d6fffTa5d6ff'Ta5d6ff<li class=Ta5d6ff"Ta5d6ffmb-2Ta5d6ff"Ta5d6ff><a href=Ta5d6ff"Tffd700{Te6edf3htmlTff7b72.Td2a8ffescapeTb4b4b4(Te6edf3html_fileTb4b4b4)Tffd700}Ta5d6ff"Ta5d6ff class=Ta5d6ff"Ta5d6fftext-blue-400 hover:text-blue-300Ta5d6ff"Ta5d6ff>Tffd700{Te6edf3htmlTff7b72.Td2a8ffescapeTb4b4b4(Te6edf3labelTb4b4b4)Tffd700}Ta5d6ff</a></li>Ta5d6ff'Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3index_linksTb4b4b4:
Te6edf3index_html Tff7b72= Tff7b72selfTff7b72.Td2a8ff_standalone_html_shellTb4b4b4(
Ta5d6ff"Ta5d6ffMeshChatX DocumentationTa5d6ff"Tb4b4b4,
Ta5d6fffTa5d6ff'Ta5d6ff<h1 class=Ta5d6ff"Ta5d6fftext-2xl font-bold mb-4Ta5d6ff"Ta5d6ff>MeshChatX Documentation</h1><ul class=Ta5d6ff"Ta5d6fflist-none pl-0Ta5d6ff"Ta5d6ff>Tffd700{Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3index_linksTb4b4b4)Tffd700}Ta5d6ff</ul>Ta5d6ff'Tb4b4b4,
Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4, Ta5d6ff"Ta5d6ffindex.htmlTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4,
Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4,
Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3index_htmlTb4b4b4)
Tff7b72def Td2a8ff_write_doc_html_exportTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rel_pathTb4b4b4)Tb4b4b4:
Te6edf3full_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4, Te6edf3rel_pathTb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3full_pathTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3full_pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3content Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3rel_pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.mdTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3body Tff7b72= Te6edf3MarkdownRendererTff7b72.Td2a8ffrenderTb4b4b4(Te6edf3contentTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3body Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ff<pre class=Ta5d6ff'Ta5d6ffwhitespace-pre-wrap font-monoTa5d6ff'Ta5d6ff>Tffd700{Te6edf3htmlTff7b72.Td2a8ffescapeTb4b4b4(Te6edf3contentTb4b4b4)Tffd700}Ta5d6ff</pre>Ta5d6ff"
Te6edf3title Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3rel_pathTb4b4b4)
Te6edf3html_file Tff7b72= Tff7b72selfTff7b72.Td2a8ff_doc_html_nameTb4b4b4(Te6edf3rel_pathTb4b4b4)
Te6edf3html_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4, Te6edf3html_fileTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3html_pathTb4b4b4)Tb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3doc_html Tff7b72= Tff7b72selfTff7b72.Td2a8ff_standalone_html_shellTb4b4b4(
Te6edf3titleTb4b4b4, Ta5d6fffTa5d6ff'Ta5d6ff<div class=Ta5d6ff"Ta5d6ffmax-w-none break-wordsTa5d6ff"Ta5d6ff>Tffd700{Te6edf3bodyTffd700}Ta5d6ff</div>Ta5d6ff'
Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3html_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3doc_htmlTb4b4b4)
Tff7b72return Te6edf3html_file
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to render Tffd700{Te6edf3rel_pathTffd700}Ta5d6ff to HTML: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72None
Tf0883e@staticmethod
Tff7b72def Td2a8ff_doc_html_nameTb4b4b4(Te6edf3rel_pathTb4b4b4)Tb4b4b4:
Te6edf3baseTb4b4b4, Te6edf3_ext Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffsplitextTb4b4b4(Te6edf3rel_pathTb4b4b4)
Tff7b72return Ta5d6fffTa5d6ff"Tffd700{Te6edf3baseTffd700}Ta5d6ff.htmlTa5d6ff"
Tf0883e@staticmethod
Tff7b72def Td2a8ff_standalone_html_shellTb4b4b4(Te6edf3titleTb4b4b4, Te6edf3body_htmlTb4b4b4)Tb4b4b4:
Te6edf3safe_title Tff7b72= Te6edf3htmlTff7b72.Td2a8ffescapeTb4b4b4(Te6edf3titleTb4b4b4)
Tff7b72return Ta5d6fffTa5d6ff"""Ta5d6ff<!DOCTYPE html>
Ta5d6ff<html lang=Ta5d6ff"Ta5d6ffenTa5d6ff"Ta5d6ff>
Ta5d6ff<head>
Ta5d6ff <meta charset=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Ta5d6ff>
Ta5d6ff <meta name=Ta5d6ff"Ta5d6ffviewportTa5d6ff"Ta5d6ff content=Ta5d6ff"Ta5d6ffwidth=device-width, initial-scale=1Ta5d6ff"Ta5d6ff>
Ta5d6ff <meta name=Ta5d6ff"Ta5d6ffcolor-schemeTa5d6ff"Ta5d6ff content=Ta5d6ff"Ta5d6fflight darkTa5d6ff"Ta5d6ff>
Ta5d6ff <title>Tffd700{Te6edf3safe_titleTffd700}Ta5d6ff</title>
Ta5d6ff <script src=Ta5d6ff"Ta5d6ff/assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.jsTa5d6ff"Ta5d6ff></script>
Ta5d6ff <style>
Ta5d6ff :root Tffea00{{
Ta5d6ff color-scheme: light dark;
Ta5d6ff --mc-bg: #f8fafc;
Ta5d6ff --mc-fg: #111827;
Ta5d6ff --mc-muted: #6b7280;
Ta5d6ff --mc-code-bg: #1e293b;
Ta5d6ff --mc-code-fg: #f1f5f9;
Ta5d6ff --mc-border: #e5e7eb;
Ta5d6ff Tffea00}}
Ta5d6ff @media (prefers-color-scheme: dark) Tffea00{{
Ta5d6ff :root Tffea00{{
Ta5d6ff --mc-bg: #09090b;
Ta5d6ff --mc-fg: #f4f4f5;
Ta5d6ff --mc-muted: #a1a1aa;
Ta5d6ff --mc-code-bg: #18181b;
Ta5d6ff --mc-code-fg: #f4f4f5;
Ta5d6ff --mc-border: #3f3f46;
Ta5d6ff Tffea00}}
Ta5d6ff Tffea00}}
Ta5d6ff body Tffea00{{
Ta5d6ff background-color: var(--mc-bg);
Ta5d6ff color: var(--mc-fg);
Ta5d6ff Tffea00}}
Ta5d6ff a Tffea00{{Ta5d6ff color: #2563eb; Tffea00}}
Ta5d6ff @media (prefers-color-scheme: dark) Tffea00{{
Ta5d6ff a Tffea00{{Ta5d6ff color: #60a5fa; Tffea00}}
Ta5d6ff Tffea00}}
Ta5d6ff pre, code Tffea00{{
Ta5d6ff background-color: var(--mc-code-bg);
Ta5d6ff color: var(--mc-code-fg);
Ta5d6ff Tffea00}}
Ta5d6ff th, td Tffea00{{Ta5d6ff border-color: var(--mc-border); Tffea00}}
Ta5d6ff </style>
Ta5d6ff</head>
Ta5d6ff<body class=Ta5d6ff"Ta5d6ffp-4 md:p-8 max-w-4xl mx-autoTa5d6ff"Ta5d6ff>
Ta5d6ff Tffd700{Te6edf3body_htmlTffd700}
Ta5d6ff</body>
Ta5d6ff</html>Ta5d6ff"""
Tff7b72def Td2a8ffget_statusTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffupload_statusTb4b4b4,
Ta5d6ff"Ta5d6ffprogressTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffupload_progressTb4b4b4,
Ta5d6ff"Ta5d6fflast_errorTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8fflast_errorTb4b4b4,
Ta5d6ff"Ta5d6ffhas_docsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffhas_docsTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffhas_bundled_docsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffhas_bundled_docsTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffhas_user_docsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffhas_user_docsTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffhas_meshchatx_docsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffhas_meshchatx_docsTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffversionsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffget_available_versionsTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffcurrent_versionTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffget_current_versionTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ffhas_meshchatx_docsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_collect_flat_docsTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72> T79c0ff0
Tff7b72def Td2a8ffget_meshchatx_docs_listTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3langTff7b72=Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3manifestTb4b4b4, Te6edf3manifest_error Tff7b72= Tff7b72selfTff7b72.Td2a8ff_read_manifestTb4b4b4(Tb4b4b4)
Te6edf3flat_docs Tff7b72= Tff7b72selfTff7b72.Td2a8ff_collect_flat_docsTb4b4b4(Tb4b4b4)
Te6edf3languages Tff7b72= Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflanguagesTa5d6ff"Tb4b4b4) Tff7b72if Te6edf3manifest Tff7b72else Tff7b72None
Tff7b72if Tff7b72not Te6edf3languagesTb4b4b4:
Te6edf3languages Tff7b72= Tb4b4b4[Tb4b4b4{Ta5d6ff"Ta5d6ffcodeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffEnglishTa5d6ff"Tb4b4b4}Tb4b4b4]
Te6edf3default_language Tff7b72= Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdefault_languageTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4) Tff7b72if Te6edf3manifest Tff7b72else Ta5d6ff"Ta5d6ffenTa5d6ff"
Te6edf3sections Tff7b72= Tff7b72selfTff7b72.Td2a8ff_build_sectionsTb4b4b4(Te6edf3manifestTb4b4b4, Te6edf3langTb4b4b4, Te6edf3default_languageTb4b4b4, Te6edf3flat_docsTb4b4b4)
Te6edf3result Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffdocsTa5d6ff"Tb4b4b4: Te6edf3flat_docsTb4b4b4,
Ta5d6ff"Ta5d6ffsectionsTa5d6ff"Tb4b4b4: Te6edf3sectionsTb4b4b4,
Ta5d6ff"Ta5d6fflanguagesTa5d6ff"Tb4b4b4: Te6edf3languagesTb4b4b4,
Ta5d6ff"Ta5d6ffdefault_languageTa5d6ff"Tb4b4b4: Te6edf3default_languageTb4b4b4,
Tb4b4b4}
Tff7b72if Te6edf3manifest_errorTb4b4b4:
Te6edf3resultTb4b4b4[Ta5d6ff"Ta5d6ffmanifest_errorTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3manifest_error
Tff7b72return Te6edf3result
Tf0883e@staticmethod
Tff7b72def Td2a8ff_is_safe_doc_pathTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3path Tff7b72or Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3pathTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Tff7b72if Ta5d6ff"Tffea00\0Ta5d6ff" Tff7b72in Te6edf3pathTb4b4b4:
Tff7b72return Tff7b72False
Te6edf3normalized Tff7b72= Te6edf3pathTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Tffea00\\Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3normalized Tff7b72or Te6edf3normalizedTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72False
Te6edf3parts Tff7b72= Tb4b4b4[Te6edf3part Tff7b72for Te6edf3part Tff7b72in Te6edf3normalizedTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4) Tff7b72if Te6edf3part Tff7b72not Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4)Tb4b4b4]
Tff7b72return Ta5d6ff"Ta5d6ff..Ta5d6ff" Tff7b72not Tff7b72in Te6edf3parts
Tff7b72def Td2a8ff_read_manifestTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3manifest_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4, Te6edf3MANIFEST_FILENAMETb4b4b4)
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3manifest_pathTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72NoneTb4b4b4, Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3manifest_pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadTb4b4b4(Te6edf3fTb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72NoneTb4b4b4, Ta5d6ff"Ta5d6ffManifest must be a JSON objectTa5d6ff"
Tff7b72return Te6edf3dataTb4b4b4, Tff7b72None
Tff7b72except Te6edf3jsonTff7b72.Td2a8ffJSONDecodeError Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to parse docs manifest: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72NoneTb4b4b4, Ta5d6ff"Ta5d6ffInvalid manifest JSONTa5d6ff"
Tff7b72except Tf85149OSError Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to read docs manifest: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72NoneTb4b4b4, Ta5d6ff"Ta5d6ffCould not read manifest fileTa5d6ff"
Tff7b72def Td2a8ff_collect_flat_docsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3docs Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3docs
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3filesTb4b4b4:
Tff7b72if Tff7b72not Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Te6edf3DOC_FILE_SUFFIXESTb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3file_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3rel_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3file_pathTb4b4b4, Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72continue
Te6edf3rel_path Tff7b72= Te6edf3rel_pathTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Tffea00\\Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)
Te6edf3docsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3fileTb4b4b4,
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3rel_pathTb4b4b4,
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffmarkdownTa5d6ff" Tff7b72if Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.mdTa5d6ff"Tb4b4b4) Tff7b72else Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Tffa657sortedTb4b4b4(Te6edf3docsTb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3xTb4b4b4: Te6edf3xTb4b4b4[Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72def Td2a8ff_build_sectionsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3manifestTb4b4b4, Te6edf3langTb4b4b4, Te6edf3default_languageTb4b4b4, Te6edf3flat_docsTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3manifest Tff7b72or Tff7b72not Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsectionsTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffallTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_localized_textTb4b4b4(
Tb4b4b4{Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffGuidesTa5d6ff"Tb4b4b4}Tb4b4b4, Te6edf3langTb4b4b4, Te6edf3default_language
Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffitemsTa5d6ff"Tb4b4b4: Tb4b4b4[
Tb4b4b4{
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3docTb4b4b4[Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_title_from_pathTb4b4b4(Te6edf3docTb4b4b4[Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fflangTa5d6ff"Tb4b4b4: Te6edf3default_languageTb4b4b4,
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Te6edf3docTb4b4b4[Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4}
Tff7b72for Te6edf3doc Tff7b72in Te6edf3flat_docs
Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4]
Te6edf3available Tff7b72= Tb4b4b4{Te6edf3docTb4b4b4[Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4] Tff7b72for Te6edf3doc Tff7b72in Te6edf3flat_docsTb4b4b4}
Te6edf3sections Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3section Tff7b72in Tffa657sortedTb4b4b4(
Te6edf3manifestTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsectionsTa5d6ff"Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4, Te6edf3keyTff7b72=Tff7b72lambda Te6edf3sTb4b4b4: Te6edf3sTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fforderTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)
Tb4b4b4)Tb4b4b4:
Te6edf3items Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3item Tff7b72in Te6edf3sectionTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffitemsTa5d6ff"Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4:
Te6edf3rel_path Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3rel_path Tff7b72or Te6edf3rel_path Tff7b72not Tff7b72in Te6edf3availableTb4b4b4:
Tff7b72continue
Te6edf3item_lang Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflangTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3default_language
Te6edf3doc_type Tff7b72= Ta5d6ff"Ta5d6ffmarkdownTa5d6ff" Tff7b72if Te6edf3rel_pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.mdTa5d6ff"Tb4b4b4) Tff7b72else Ta5d6ff"Ta5d6fftextTa5d6ff"
Te6edf3itemsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3rel_pathTb4b4b4,
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_localized_textTb4b4b4(
Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3langTb4b4b4,
Te6edf3item_lang Tff7b72or Te6edf3default_languageTb4b4b4,
Tb4b4b4)
Tff7b72or Tff7b72selfTff7b72.Td2a8ff_title_from_pathTb4b4b4(Te6edf3rel_pathTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fflangTa5d6ff"Tb4b4b4: Te6edf3item_langTb4b4b4,
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Te6edf3doc_typeTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3itemsTb4b4b4:
Te6edf3sectionsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Te6edf3sectionTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3sectionTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsectionTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_localized_textTb4b4b4(
Te6edf3sectionTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3langTb4b4b4,
Te6edf3default_languageTb4b4b4,
Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffitemsTa5d6ff"Tb4b4b4: Te6edf3itemsTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3sections
Tf0883e@staticmethod
Tff7b72def Td2a8ff_localized_textTb4b4b4(Te6edf3valueTb4b4b4, Te6edf3langTb4b4b4, Te6edf3fallbackTff7b72=Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3value Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ff"
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3value
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3valueTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4(
Te6edf3valueTff7b72.Td2a8ffgetTb4b4b4(Te6edf3langTb4b4b4) Tff7b72or Te6edf3valueTff7b72.Td2a8ffgetTb4b4b4(Te6edf3fallbackTb4b4b4) Tff7b72or Tffa657nextTb4b4b4(Tffa657iterTb4b4b4(Te6edf3valueTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tb4b4b4)
Tff7b72return Tffa657strTb4b4b4(Te6edf3valueTb4b4b4)
Tf0883e@staticmethod
Tff7b72def Td2a8ff_title_from_pathTb4b4b4(Te6edf3rel_pathTb4b4b4)Tb4b4b4:
Te6edf3base Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3rel_pathTb4b4b4)
Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffsplitextTb4b4b4(Te6edf3baseTb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Ta5d6ff-Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ff"Ta5d6ff_Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffget_doc_contentTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_is_safe_doc_pathTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3full_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4, Te6edf3pathTb4b4b4)Tb4b4b4)
Te6edf3base Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149ValueErrorTb4b4b4, Tf85149OSErrorTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3full_pathTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3base Tff7b72+ Te6edf3osTff7b72.Td2a8ffsepTb4b4b4) Tff7b72and Te6edf3full_path Tff7b72!= Te6edf3baseTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3full_pathTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3full_pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffignoreTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3content Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSError Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to read MeshChatX doc Tffd700{Te6edf3pathTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3pathTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.mdTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4: Te6edf3contentTb4b4b4,
Ta5d6ff"Ta5d6ffhtmlTa5d6ff"Tb4b4b4: Te6edf3MarkdownRendererTff7b72.Td2a8ffrenderTb4b4b4(Te6edf3contentTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffmarkdownTa5d6ff"Tb4b4b4,
Tb4b4b4}
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4: Te6edf3contentTb4b4b4,
Ta5d6ff"Ta5d6ffhtmlTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Ta5d6ff<pre class=Ta5d6ff'Ta5d6ffwhitespace-pre-wrap font-monoTa5d6ff'Ta5d6ff>Tffd700{Te6edf3htmlTff7b72.Td2a8ffescapeTb4b4b4(Te6edf3contentTb4b4b4)Tffd700}Ta5d6ff</pre>Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6fftextTa5d6ff"Tb4b4b4,
Tb4b4b4}
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to render MeshChatX doc Tffd700{Te6edf3pathTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72None
Tff7b72def Td2a8ffexport_docsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Build a ZIP archive containing the active Reticulum docs and MeshChatX docs."""
Te6edf3buffer Tff7b72= Te6edf3ioTff7b72.Td2a8ffBytesIOTb4b4b4(Tb4b4b4)
Te6edf3active_docs_dir Tff7b72= Tff7b72selfTff7b72.Td2a8ff_active_reticulum_docs_dirTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3zipfileTff7b72.Td2a8ffZipFileTb4b4b4(Te6edf3bufferTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3zipfileTff7b72.Td2a8ffZIP_DEFLATEDTb4b4b4) Tff7b72as Te6edf3zip_fileTb4b4b4:
Tff7b72if Te6edf3active_docs_dir Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3active_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Te6edf3active_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3filesTb4b4b4:
Te6edf3file_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)
Te6edf3rel_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(
Ta5d6ff"Ta5d6ffreticulum-docsTa5d6ff"Tb4b4b4,
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3active_docs_dirTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3zip_fileTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3rel_pathTb4b4b4)
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3filesTb4b4b4:
Te6edf3file_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)
Te6edf3rel_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(
Ta5d6ff"Ta5d6ffmeshchatx-docsTa5d6ff"Tb4b4b4,
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3file_pathTb4b4b4, Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3zip_fileTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3rel_pathTb4b4b4)
Te6edf3bufferTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72return Te6edf3bufferTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffexport_reticulum_docsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3root_folderTff7b72=Ta5d6ff"Ta5d6ffreticulum_manualTa5d6ff"Tb4b4b4)Tb4b4b4:
T8b949e"""Build a ZIP of the active Reticulum manual in upload-compatible form.
The archive lays out files under ``<root_folder>/docs/`` so that another
MeshChatX instance can re-import it via the ``/api/v1/docs/upload``
endpoint without modification. Returns ``None`` when no Reticulum docs
are currently available (neither user-uploaded nor bundled).
"""
Te6edf3active_docs_dir Tff7b72= Tff7b72selfTff7b72.Td2a8ff_active_reticulum_docs_dirTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3active_docs_dir Tff7b72or Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3active_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72None
Te6edf3safe_root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3root_folderTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ffreticulum_manualTa5d6ff"
Tff7b72if Te6edf3safe_root Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3safe_root Tff7b72= Ta5d6ff"Ta5d6ffreticulum_manualTa5d6ff"
Te6edf3buffer Tff7b72= Te6edf3ioTff7b72.Td2a8ffBytesIOTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3zipfileTff7b72.Td2a8ffZipFileTb4b4b4(Te6edf3bufferTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3zipfileTff7b72.Td2a8ffZIP_DEFLATEDTb4b4b4) Tff7b72as Te6edf3zip_fileTb4b4b4:
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Te6edf3active_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3filesTb4b4b4:
Te6edf3file_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)
Te6edf3arcname Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(
Te6edf3safe_rootTb4b4b4,
Ta5d6ff"Ta5d6ffdocsTa5d6ff"Tb4b4b4,
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3active_docs_dirTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3zip_fileTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3arcnameTb4b4b4)
Te6edf3bufferTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72return Te6edf3bufferTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffsearchTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3queryTb4b4b4, Te6edf3langTff7b72=Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3queryTb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]
Te6edf3results Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3query Tff7b72= Te6edf3queryTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3filesTb4b4b4:
Tff7b72if Tff7b72not Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Te6edf3DOC_FILE_SUFFIXESTb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3file_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(
Te6edf3file_pathTb4b4b4,
Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4,
Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffignoreTa5d6ff"Tb4b4b4,
Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3content Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3query Tff7b72in Te6edf3contentTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3idx Tff7b72= Te6edf3contentTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fffindTb4b4b4(Te6edf3queryTb4b4b4)
Te6edf3start Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3idx Tff7b72- T79c0ff80Tb4b4b4)
Te6edf3end Tff7b72= Tffa657minTb4b4b4(Tffa657lenTb4b4b4(Te6edf3contentTb4b4b4)Tb4b4b4, Te6edf3idx Tff7b72+ Tffa657lenTb4b4b4(Te6edf3queryTb4b4b4) Tff7b72+ T79c0ff120Tb4b4b4)
Te6edf3snippet Tff7b72= Te6edf3contentTb4b4b4[Te6edf3startTb4b4b4:Te6edf3endTb4b4b4]
Tff7b72if Te6edf3start Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3snippet Tff7b72= Ta5d6ff"Ta5d6ff...Ta5d6ff" Tff7b72+ Te6edf3snippet
Tff7b72if Te6edf3end Tff7b72< Tffa657lenTb4b4b4(Te6edf3contentTb4b4b4)Tb4b4b4:
Te6edf3snippet Tff7b72= Te6edf3snippet Tff7b72+ Ta5d6ff"Ta5d6ff...Ta5d6ff"
Te6edf3resultsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Te6edf3fileTb4b4b4,
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Ta5d6ff/meshchatx-docs/Tffd700{Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3file_pathTb4b4b4, Tff7b72selfTff7b72.Td2a8ffmeshchatx_docs_dirTb4b4b4)Tff7b72.Td2a8ffreplaceTb4b4b4(Te6edf3osTff7b72.Td2a8ffsepTb4b4b4, Ta5d6ff'Ta5d6ff/Ta5d6ff'Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffsnippetTa5d6ff"Tb4b4b4: Te6edf3snippetTb4b4b4,
Ta5d6ff"Ta5d6ffsourceTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffMeshChatXTa5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffError searching MeshChatX doc Tffd700{Te6edf3fileTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3active_docs_dir Tff7b72= Tff7b72selfTff7b72.Td2a8ff_active_reticulum_docs_dirTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3active_docs_dir Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3active_docs_dirTb4b4b4)Tb4b4b4:
Te6edf3known_langs Tff7b72= Tb4b4b4[Ta5d6ff"Ta5d6ffdeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffesTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffjpTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffnlTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffplTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffpt-brTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftrTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffukTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffzh-cnTa5d6ff"Tb4b4b4]
Te6edf3target_files Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72tryTb4b4b4:
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Te6edf3active_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3filesTb4b4b4:
Tff7b72if Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.htmlTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3lang Tff7b72!= Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4:
Tff7b72if Ta5d6fffTa5d6ff"Ta5d6ff_Tffd700{Te6edf3langTffd700}Ta5d6ff.htmlTa5d6ff" Tff7b72in Te6edf3fileTb4b4b4:
Te6edf3target_filesTff7b72.Td2a8ffappendTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3has_lang_suffix Tff7b72= Tff7b72False
Tff7b72for Te6edf3lang_code Tff7b72in Te6edf3known_langsTb4b4b4:
Tff7b72if Ta5d6fffTa5d6ff"Ta5d6ff_Tffd700{Te6edf3lang_codeTffd700}Ta5d6ff.htmlTa5d6ff" Tff7b72in Te6edf3fileTb4b4b4:
Te6edf3has_lang_suffix Tff7b72= Tff7b72True
Tff7b72break
Tff7b72if Tff7b72not Te6edf3has_lang_suffixTb4b4b4:
Te6edf3target_filesTff7b72.Td2a8ffappendTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3target_files Tff7b72and Te6edf3lang Tff7b72!= Ta5d6ff"Ta5d6ffenTa5d6ff"Tb4b4b4:
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3_Tb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Te6edf3active_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3file Tff7b72in Te6edf3filesTb4b4b4:
Tff7b72if Te6edf3fileTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.htmlTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3has_lang_suffix Tff7b72= Tff7b72False
Tff7b72for Te6edf3lang_code Tff7b72in Te6edf3known_langsTb4b4b4:
Tff7b72if Ta5d6fffTa5d6ff"Ta5d6ff_Tffd700{Te6edf3lang_codeTffd700}Ta5d6ff.htmlTa5d6ff" Tff7b72in Te6edf3fileTb4b4b4:
Te6edf3has_lang_suffix Tff7b72= Tff7b72True
Tff7b72break
Tff7b72if Tff7b72not Te6edf3has_lang_suffixTb4b4b4:
Te6edf3target_filesTff7b72.Td2a8ffappendTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3fileTb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3file_path Tff7b72in Te6edf3target_filesTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4, Te6edf3errorsTff7b72=Ta5d6ff"Ta5d6ffignoreTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3content Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Te6edf3text_content Tff7b72= Te6edf3reTff7b72.Td2a8ffsubTb4b4b4(Ta5d6ffrTa5d6ff"Ta5d6ff<[^>]+>Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4, Te6edf3contentTb4b4b4)
Te6edf3text_content Tff7b72= Ta5d6ff"Ta5d6ff Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3text_contentTff7b72.Td2a8ffsplitTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3query Tff7b72in Te6edf3text_contentTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3title_match Tff7b72= Te6edf3reTff7b72.Td2a8ffsearchTb4b4b4(
Ta5d6ffrTa5d6ff"Ta5d6ff<title>(.*?)</title>Ta5d6ff"Tb4b4b4,
Te6edf3contentTb4b4b4,
Te6edf3reTff7b72.Td2a8ffIGNORECASE Tff7b72| Te6edf3reTff7b72.Td2a8ffDOTALLTb4b4b4,
Tb4b4b4)
Te6edf3title Tff7b72= Tb4b4b4(
Te6edf3title_matchTff7b72.Td2a8ffgroupTb4b4b4(T79c0ff1Tb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3title_match
Tff7b72else Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3file_pathTb4b4b4)
Tb4b4b4)
Te6edf3title Tff7b72= Te6edf3reTff7b72.Td2a8ffsubTb4b4b4(Ta5d6ffrTa5d6ff"Ta5d6ff\Ta5d6ffs+[Ta5d6ff\Ta5d6ffu2014-].*$Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4, Te6edf3titleTb4b4b4)
Te6edf3idx Tff7b72= Te6edf3text_contentTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fffindTb4b4b4(Te6edf3queryTb4b4b4)
Te6edf3start Tff7b72= Tffa657maxTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3idx Tff7b72- T79c0ff80Tb4b4b4)
Te6edf3end Tff7b72= Tffa657minTb4b4b4(Tffa657lenTb4b4b4(Te6edf3text_contentTb4b4b4)Tb4b4b4, Te6edf3idx Tff7b72+ Tffa657lenTb4b4b4(Te6edf3queryTb4b4b4) Tff7b72+ T79c0ff120Tb4b4b4)
Te6edf3snippet Tff7b72= Te6edf3text_contentTb4b4b4[Te6edf3startTb4b4b4:Te6edf3endTb4b4b4]
Tff7b72if Te6edf3start Tff7b72> T79c0ff0Tb4b4b4:
Te6edf3snippet Tff7b72= Ta5d6ff"Ta5d6ff...Ta5d6ff" Tff7b72+ Te6edf3snippet
Tff7b72if Te6edf3end Tff7b72< Tffa657lenTb4b4b4(Te6edf3text_contentTb4b4b4)Tb4b4b4:
Te6edf3snippet Tff7b72= Te6edf3snippet Tff7b72+ Ta5d6ff"Ta5d6ff...Ta5d6ff"
Te6edf3rel_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3active_docs_dirTb4b4b4)
Te6edf3resultsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Te6edf3titleTb4b4b4,
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Ta5d6ff/reticulum-docs/Tffd700{Te6edf3rel_pathTffd700}Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffsnippetTa5d6ff"Tb4b4b4: Te6edf3snippetTb4b4b4,
Ta5d6ff"Ta5d6ffsourceTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffReticulumTa5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3resultsTb4b4b4) Tff7b72>Tff7b72= T79c0ff25Tb4b4b4:
Tff7b72break
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffError searching file Tffd700{Te6edf3file_pathTffd700}Ta5d6ff: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffSearch failed: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3results
Tff7b72def Td2a8ffhas_docsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""True if either user-uploaded or bundled Reticulum docs are available."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffhas_user_docsTb4b4b4(Tb4b4b4) Tff7b72or Tff7b72selfTff7b72.Td2a8ffhas_bundled_docsTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffhas_user_docsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4, Ta5d6ff"Ta5d6ffindex.htmlTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72True
Tff7b72return Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffget_available_versionsTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72> T79c0ff0
Tff7b72def Td2a8ffhas_bundled_docsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbundled_docs_dirTb4b4b4, Ta5d6ff"Ta5d6ffindex.htmlTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72def Td2a8fffind_docs_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3rel_pathTb4b4b4)Tb4b4b4:
T8b949e"""Resolve ``rel_path`` against user docs first, then bundled docs.
Returns the absolute on-disk path of the matching file, or ``None`` when
the path either escapes the docs roots or no file exists in either
location. Path traversal attempts are rejected.
"""
Tff7b72if Te6edf3rel_path Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3rel_path Tff7b72= Ta5d6ff"Ta5d6ff"
Tff7b72for Te6edf3base Tff7b72in Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4, Tff7b72selfTff7b72.Td2a8ffbundled_docs_dirTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3base Tff7b72or Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3baseTb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72tryTb4b4b4:
Te6edf3candidate Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3baseTb4b4b4, Te6edf3rel_pathTb4b4b4)Tb4b4b4)
Te6edf3base_real Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3baseTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149ValueErrorTb4b4b4, Tf85149OSErrorTb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3candidate Tff7b72!= Te6edf3base_real Tff7b72and Tff7b72not Te6edf3candidateTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3base_real Tff7b72+ Te6edf3osTff7b72.Td2a8ffsepTb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3candidateTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3candidate
Tff7b72return Tff7b72None
Tff7b72def Td2a8ff_active_reticulum_docs_dirTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_dirTb4b4b4, Ta5d6ff"Ta5d6ffindex.htmlTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffdocs_dir
Tff7b72if Tff7b72selfTff7b72.Td2a8ffhas_bundled_docsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffbundled_docs_dir
Tff7b72return Tff7b72None
Tff7b72def Td2a8ffupload_zipTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3zip_bytesTb4b4b4, Te6edf3versionTb4b4b4)Tb4b4b4:
T8b949e"""Extract a user-uploaded docs ZIP into a new version and switch to it."""
Tff7b72selfTff7b72.Td2a8ffupload_status Tff7b72= Ta5d6ff"Ta5d6ffextractingTa5d6ff"
Tff7b72selfTff7b72.Td2a8ffupload_progress Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3zip_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_base_dirTb4b4b4, Ta5d6ff"Ta5d6ffuploaded.zipTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3zip_pathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3zip_bytesTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_extract_docsTb4b4b4(Te6edf3zip_pathTb4b4b4, Te6edf3versionTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3zip_pathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3zip_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffupload_status Tff7b72= Ta5d6ff"Ta5d6ffcompletedTa5d6ff"
Tff7b72selfTff7b72.Td2a8ffupload_progress Tff7b72= T79c0ff100
Tff7b72selfTff7b72.Td2a8ffswitch_versionTb4b4b4(Te6edf3versionTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflast_error Tff7b72= Tffa657strTb4b4b4(Te6edf3eTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffupload_status Tff7b72= Ta5d6ff"Ta5d6fferrorTa5d6ff"
Te6edf3loggingTff7b72.Td2a8ffexceptionTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to upload docs: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Tff7b72False
Tff7b72def Td2a8ff_extract_docsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3zip_pathTb4b4b4, Te6edf3versionTb4b4b4)Tb4b4b4:
Te6edf3safe_version Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffbasenameTb4b4b4(Te6edf3versionTb4b4b4)
Tff7b72if Tff7b72not Te6edf3safe_version Tff7b72or Te6edf3safe_version Tff7b72in Tb4b4b4(Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff..Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffInvalid version name: Tffd700{Te6edf3versionTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3version_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4, Te6edf3safe_versionTb4b4b4)
Te6edf3resolved Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3version_dirTb4b4b4)
Te6edf3base Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tff7b72selfTff7b72.Td2a8ffversions_dirTb4b4b4)
Tff7b72if Tff7b72not Te6edf3resolvedTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3base Tff7b72+ Te6edf3osTff7b72.Td2a8ffsepTb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffInvalid version name: Tffd700{Te6edf3versionTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3version_dirTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_remove_tree_force_writableTb4b4b4(Te6edf3version_dirTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3version_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_dir_writableTb4b4b4(Te6edf3version_dirTb4b4b4)
Te6edf3temp_extract Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdocs_base_dirTb4b4b4, Ta5d6ff"Ta5d6fftemp_extractTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3temp_extractTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_remove_tree_force_writableTb4b4b4(Te6edf3temp_extractTb4b4b4)
Tff7b72with Te6edf3zipfileTff7b72.Td2a8ffZipFileTb4b4b4(Te6edf3zip_pathTb4b4b4, Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3zip_refTb4b4b4:
Te6edf3namelist Tff7b72= Te6edf3zip_refTff7b72.Td2a8ffnamelistTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3namelistTb4b4b4:
Tff7b72raise Tf85149ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffZip file is emptyTa5d6ff"Tb4b4b4)
Te6edf3root_folder Tff7b72= Te6edf3namelistTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3docs_prefix Tff7b72= Ta5d6fffTa5d6ff"Tffd700{Te6edf3root_folderTffd700}Ta5d6ff/docs/Ta5d6ff"
Te6edf3has_docs_subfolder Tff7b72= Tffa657anyTb4b4b4(Te6edf3mTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3docs_prefixTb4b4b4) Tff7b72for Te6edf3m Tff7b72in Te6edf3namelistTb4b4b4)
Tff7b72if Te6edf3has_docs_subfolderTb4b4b4:
Te6edf3members_to_extract Tff7b72= Tb4b4b4[Te6edf3m Tff7b72for Te6edf3m Tff7b72in Te6edf3namelist Tff7b72if Te6edf3mTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3docs_prefixTb4b4b4)Tb4b4b4]
Tff7b72for Te6edf3member Tff7b72in Te6edf3members_to_extractTb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ff..Ta5d6ff" Tff7b72in Te6edf3memberTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3zip_refTff7b72.Td2a8ffextractTb4b4b4(Te6edf3memberTb4b4b4, Te6edf3temp_extractTb4b4b4)
Te6edf3src_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3temp_extractTb4b4b4, Te6edf3root_folderTb4b4b4, Ta5d6ff"Ta5d6ffdocsTa5d6ff"Tb4b4b4)
Tff7b72for Te6edf3item Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3src_pathTb4b4b4)Tb4b4b4:
Te6edf3s Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3src_pathTb4b4b4, Te6edf3itemTb4b4b4)
Te6edf3d Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3version_dirTb4b4b4, Te6edf3itemTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_copy_tree_no_metadataTb4b4b4(Te6edf3sTb4b4b4, Te6edf3dTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_copy_file_no_metadataTb4b4b4(Te6edf3sTb4b4b4, Te6edf3dTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3safe_members Tff7b72= Tb4b4b4[Te6edf3m Tff7b72for Te6edf3m Tff7b72in Te6edf3namelist Tff7b72if Ta5d6ff"Ta5d6ff..Ta5d6ff" Tff7b72not Tff7b72in Te6edf3mTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)Tb4b4b4]
Te6edf3zip_refTff7b72.Td2a8ffextractallTb4b4b4(Te6edf3temp_extractTb4b4b4, Te6edf3membersTff7b72=Te6edf3safe_membersTb4b4b4)
Te6edf3src_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3temp_extractTb4b4b4, Te6edf3root_folderTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3src_pathTb4b4b4) Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3src_pathTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3item Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3src_pathTb4b4b4)Tb4b4b4:
Te6edf3s Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3src_pathTb4b4b4, Te6edf3itemTb4b4b4)
Te6edf3d Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3version_dirTb4b4b4, Te6edf3itemTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_copy_tree_no_metadataTb4b4b4(Te6edf3sTb4b4b4, Te6edf3dTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_copy_file_no_metadataTb4b4b4(Te6edf3sTb4b4b4, Te6edf3dTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72for Te6edf3item Tff7b72in Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3temp_extractTb4b4b4)Tb4b4b4:
Te6edf3s Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3temp_extractTb4b4b4, Te6edf3itemTb4b4b4)
Te6edf3d Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3version_dirTb4b4b4, Te6edf3itemTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_copy_tree_no_metadataTb4b4b4(Te6edf3sTb4b4b4, Te6edf3dTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_copy_file_no_metadataTb4b4b4(Te6edf3sTb4b4b4, Te6edf3dTb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3version_dirTb4b4b4, Ta5d6ff"Ta5d6ff.versionTa5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3versionTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3temp_extractTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_remove_tree_force_writableTb4b4b4(Te6edf3temp_extractTb4b4b4)
Tff7b72def Td2a8ff_ensure_dir_writableTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3osTff7b72.Td2a8ffchmodTb4b4b4(Te6edf3pathTb4b4b4, T79c0ff0o755Tb4b4b4) T8b949e# noqa: S103
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72pass
Tff7b72def Td2a8ff_remove_tree_force_writableTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3dirsTb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3topdownTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3name Tff7b72in Te6edf3filesTb4b4b4:
Te6edf3file_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3nameTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3osTff7b72.Td2a8ffchmodTb4b4b4(Te6edf3file_pathTb4b4b4, T79c0ff0o644Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72pass
Tff7b72for Te6edf3name Tff7b72in Te6edf3dirsTb4b4b4:
Te6edf3dir_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3nameTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_dir_writableTb4b4b4(Te6edf3dir_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_dir_writableTb4b4b4(Te6edf3pathTb4b4b4)
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72def Td2a8ff_copy_file_no_metadataTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3srcTb4b4b4, Te6edf3dstTb4b4b4)Tb4b4b4:
Te6edf3parent Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Te6edf3dstTb4b4b4)
Tff7b72if Te6edf3parentTb4b4b4:
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3parentTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_dir_writableTb4b4b4(Te6edf3parentTb4b4b4)
Te6edf3shutilTff7b72.Td2a8ffcopyfileTb4b4b4(Te6edf3srcTb4b4b4, Te6edf3dstTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3osTff7b72.Td2a8ffchmodTb4b4b4(Te6edf3dstTb4b4b4, T79c0ff0o644Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72pass
Tff7b72def Td2a8ff_copy_tree_no_metadataTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3srcTb4b4b4, Te6edf3dstTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3dstTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_dir_writableTb4b4b4(Te6edf3dstTb4b4b4)
Tff7b72for Te6edf3rootTb4b4b4, Te6edf3dirsTb4b4b4, Te6edf3files Tff7b72in Te6edf3osTff7b72.Td2a8ffwalkTb4b4b4(Te6edf3srcTb4b4b4)Tb4b4b4:
Te6edf3rel_root Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrelpathTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3srcTb4b4b4)
Te6edf3target_root Tff7b72= Te6edf3dst Tff7b72if Te6edf3rel_root Tff7b72== Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72else Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3dstTb4b4b4, Te6edf3rel_rootTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3target_rootTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_dir_writableTb4b4b4(Te6edf3target_rootTb4b4b4)
Tff7b72for Te6edf3dirname Tff7b72in Te6edf3dirsTb4b4b4:
Te6edf3target_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3target_rootTb4b4b4, Te6edf3dirnameTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3target_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_dir_writableTb4b4b4(Te6edf3target_dirTb4b4b4)
Tff7b72for Te6edf3filename Tff7b72in Te6edf3filesTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_copy_file_no_metadataTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rootTb4b4b4, Te6edf3filenameTb4b4b4)Tb4b4b4,
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3target_rootTb4b4b4, Te6edf3filenameTb4b4b4)Tb4b4b4,
Tb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────